package cn.jinbyte.core.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * Jackson序列化工具类
 *
 * @author jintingying
 * @since 2024/5/28
 */
@SuppressWarnings("unused")
@Slf4j
@UtilityClass
public class JsonUtils {

    public final ObjectMapper objectMapper = new ObjectMapper();

    public static String serialize(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj.getClass() == String.class) {
            return (String) obj;
        }
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("json序列化出错！");
            return null;
        }
    }

    public static <T> T parse(String json, Class<T> tClass) {
        try {
            return objectMapper.readValue(json, tClass);
        } catch (IOException e) {
            log.error("解析指定类型JSON失败: {}", e.getMessage());
            return null;
        }
    }

    public static <E> List<E> parseList(String json, Class<E> eClass) {
        try {
            return objectMapper.readValue(json,
                    objectMapper.getTypeFactory().constructCollectionType(List.class, eClass));
        } catch (IOException e) {
            log.error("解析List类型JSON失败: {}", e.getMessage());
            return null;
        }
    }

    public static <K, V> Map<K, V> parseMap(String json, Class<K> kClass, Class<V> vClass) {
        try {
            return objectMapper.readValue(json,
                    objectMapper.getTypeFactory().constructMapType(Map.class, kClass, vClass));
        } catch (IOException e) {
            log.error("解析Map类型JSON失败: {}", e.getMessage());
            return null;
        }
    }

    public static <T> T nativeRead(String json, TypeReference<T> type) {
        try {
            return objectMapper.readValue(json, type);
        } catch (IOException e) {
            log.error("本地解析JSON失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 将JSON字符串解析为JsonNode
     *
     * @param json JSON字符串
     * @return JsonNode对象，解析失败返回null
     */
    public static JsonNode parseJson(String json) {
        if (json == null || json.trim().isEmpty()) {
            return null;
        }

        try {
            return objectMapper.readTree(json);
        } catch (JsonProcessingException e) {
            log.error("解析JSON失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 将输入流中的JSON数据解析为JsonNode
     *
     * @param inputStream 包含JSON数据的输入流
     * @return JsonNode对象，解析失败返回null
     */
    public static JsonNode parseJson(InputStream inputStream) {
        if (inputStream == null) {
            return null;
        }

        try {
            return objectMapper.readTree(inputStream);
        } catch (IOException e) {
            log.error("从输入流解析JSON失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 将对象转换为JSON字符串
     *
     * @param obj 要转换的对象
     * @return JSON字符串，转换失败返回null
     */
    public static String toJsonString(Object obj) {
        if (obj == null) {
            return null;
        }

        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("对象转换为JSON失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 递归处理JSON中的所有字段和值
     *
     * @param jsonNode 要处理的JSON节点
     * @param consumer 处理函数，接收字段名和对应值
     */
    public static void processJsonNode(JsonNode jsonNode, Consumer<Map.Entry<String, String>> consumer) {
        if (jsonNode == null || consumer == null) {
            return;
        }

        // 如果是对象节点，遍历所有字段
        if (jsonNode.isObject()) {
            ObjectNode objectNode = (ObjectNode) jsonNode;
            Iterator<Map.Entry<String, JsonNode>> fields = objectNode.fields();

            while (fields.hasNext()) {
                Map.Entry<String, JsonNode> entry = fields.next();
                String fieldName = entry.getKey();
                JsonNode fieldValue = entry.getValue();

                // 处理当前字段
                consumer.accept(Map.entry(fieldName, fieldValue.asText()));

                // 递归处理子节点
                processJsonNode(fieldValue, consumer);
            }
        }
        // 如果是数组节点，遍历所有元素
        else if (jsonNode.isArray()) {
            ArrayNode arrayNode = (ArrayNode) jsonNode;
            for (JsonNode element : arrayNode) {
                processJsonNode(element, consumer);
            }
        }
    }

    /**
     * 检查JSON中是否包含符合条件的值
     *
     * @param json      JSON字符串
     * @param predicate 检查条件
     * @return 如果有符合条件的值返回true，否则返回false
     */
    public static boolean checkJson(String json, java.util.function.Predicate<String> predicate) {
        JsonNode jsonNode = parseJson(json);
        return checkJsonNode(jsonNode, predicate);
    }

    /**
     * 检查JsonNode中是否包含符合条件的值
     *
     * @param jsonNode  JsonNode对象
     * @param predicate 检查条件
     * @return 如果有符合条件的值返回true，否则返回false
     */
    public static boolean checkJsonNode(JsonNode jsonNode, java.util.function.Predicate<String> predicate) {
        if (jsonNode == null || predicate == null) {
            return false;
        }

        // 检查当前节点的值
        if (!jsonNode.isContainerNode() && predicate.test(jsonNode.asText())) {
            return true;
        }

        // 递归检查子节点
        if (jsonNode.isObject()) {
            Iterator<JsonNode> elements = jsonNode.elements();
            while (elements.hasNext()) {
                if (checkJsonNode(elements.next(), predicate)) {
                    return true;
                }
            }
        } else if (jsonNode.isArray()) {
            for (JsonNode element : jsonNode) {
                if (checkJsonNode(element, predicate)) {
                    return true;
                }
            }
        }

        return false;
    }
}
